package com.ivmech.ITAR;

import java.io.IOException;

import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.UUID;


import android.os.Bundle;
import android.os.Build;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothDevice;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.content.Intent;
import android.content.Context;
import android.widget.Toast;
import android.widget.TextView;
import android.widget.ToggleButton;
import android.util.Log;

import android.preference.PreferenceManager;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

import com.ivmech.ITAR.R;
import com.ivmech.ITAR.Joystick.JoystickMovedListener;
import com.ivmech.ITAR.Joystick.JoystickView;

public class MainActivity extends Activity {
	
	private static final String TAG = "ITAR";
	private static final int RESULT_SETTINGS = 1;

    private BluetoothAdapter btAdapter = null;
    private BluetoothSocket btSocket = null;
    private OutputStream outStream = null;
    private ToggleButton baglan_toggle = null;
    private TextView text_out = null;
    
	private SensorManager sensorManager;
	private Sensor acc;
	private Sensor mag;
	private float[] mAcc;
    private float[] mMag;
    private float[] mTilt;
    
	private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	private static String address = "00:06:66:60:2F:CA";
	
	JoystickView joystick;
	
	public void toggleBaglan(View view) {
		boolean on = ((ToggleButton) view).isChecked();
		if (on) {
			checkBTState();
			if(btSocket.isConnected() == false) {
				connectBluetooth();
			}
		}
		else {
			disconnectBluetooth();
		}
	}
	
	public void toggleJoystick(View view) {
		boolean on = ((ToggleButton) view).isChecked();
		if (on) {
	        joystick.setOnJostickMovedListener(_listener);
		}
		else {
	        joystick.clearOnJostickMovedListener();
		}
	}
	
    private JoystickMovedListener _listener = new JoystickMovedListener() {

        @Override
        public void OnMoved(int pan, int tilt) {
        	//  txtX.setText(Integer.toString(pan));
        	//text_out.setText(Integer.toString(pan));
        	//  txtY.setText(Integer.toString(tilt));
        }

        @Override
        public void OnReleased() {
        	//txtX.setText("released");
        	//txtY.setText("released");
        }
       
        public void OnReturnedToCenter() {
                //txtX.setText("stopped");
        	//txtY.setText("stopped");
        };
    };
    
	private void refreshDisplay() {
		//String output = String.format("x is: %f\ny is: %f\nz is: %f", mAcc[0], mAcc[1], mAcc[2]);
		//String output = String.format("x is: %f\ny is: %f\nz is: %f", mMag[0], mMag[1], mMag[2]);
		String s = "";
		int x = (int)mTilt[1];
		if (x < 0) {
		    x *= -1;
		    s = String.format("MG%03d", x);
		}
		else
		{
			s = String.format("MI%03d", x);
		}
		
/*		int y = (int)mTilt[0];
		if (y < 0) {
			y *= -1;
			s = String.format("ML%03d", y);
		}
		else
		{
			s = String.format("MR%03d", y);
		}
*/
		String output = String.format("X: %f\nY: %f\nZ: %f", mTilt[0], mTilt[1], mTilt[2]);
		text_out.setText(output);
		
		if(btSocket.isConnected()) {
			sendData(s);
		}
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		baglan_toggle = (ToggleButton) findViewById(R.id.toggleButton1);
		text_out = (TextView) findViewById(R.id.textView1);
		joystick = (JoystickView) findViewById(R.id.joystickView1);
		
		sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		acc = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		mag = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
		
	    btAdapter = BluetoothAdapter.getDefaultAdapter();
	    checkBTState();
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
	    switch (item.getItemId()) {
	        case R.id.action_settings:
	            showSettings();
	            return true;
	        case R.id.action_info:
	        	//showInfo();
	        	return true;
	        default:
	            return super.onOptionsItemSelected(item);
	    }
	}
	
	private void showSettings() {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
	    Editor edit = sharedPrefs.edit();
		edit.clear();
		edit.putString("prefMac", "00:06:66:60:2F:CA");
		edit.commit();
        Intent i = new Intent(this, UserSettingActivity.class);
        startActivity(i);
	}
	
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
        case RESULT_SETTINGS:
            changePref();
            break;
        }
    }
	
    private void changePref() {
    	SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        sharedPrefs.getString("prefMac", "NULL");
     }
	
    private float[] getDirection()
    {
        float[] temp = new float[9];
        SensorManager.getRotationMatrix(temp, null,
                mAcc, mMag);
        
        //float[] R = new float[9];
        //SensorManager.remapCoordinateSystem(temp,
        //        SensorManager.AXIS_X,
        //        SensorManager.AXIS_Z, R);
      
        float[] values = new float[3];
        SensorManager.getOrientation(temp, values);
      
        for (int i=0; i < values.length; i++) {
            Double degrees = (values[i] * 180) / Math.PI;
            values[i] = degrees.floatValue();
        }
        return values;
    }
	
	private SensorEventListener accelerationListener = new SensorEventListener() {
		@Override
		public void onAccuracyChanged(Sensor sensor, int acc) {
		}

		@Override
		public void onSensorChanged(SensorEvent event) {
			
            switch (event.sensor.getType()) {
            case Sensor.TYPE_ACCELEROMETER:
            	mAcc = event.values.clone();
                break;

            case Sensor.TYPE_MAGNETIC_FIELD:
            	mMag = event.values.clone();
                break;
    		default:
                return;
            }
            
            if(mAcc != null && mMag != null) {
                mTilt = getDirection();
            	refreshDisplay();
            }
		}
	};	

	private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
		if(Build.VERSION.SDK_INT >= 10){
			try {
				final Method  m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
				return (BluetoothSocket) m.invoke(device, MY_UUID);
			}
			catch (Exception e) {
				Log.e(TAG, "Could not create Insecure RFComm Connection",e);
			}
		}
		return  device.createRfcommSocketToServiceRecord(MY_UUID);
	}

	private void connectBluetooth() {
		Log.d(TAG, "...onResume - try connect...");
		BluetoothDevice device = btAdapter.getRemoteDevice(address);

		try {
	    	btSocket = createBluetoothSocket(device);
	    }
	    catch (IOException e1) {
	    	baglan_toggle.setChecked(false);
	    	errorExit("Fatal Error", "In onResume() and socket create failed: " + e1.getMessage() + ".");
	    }

		btAdapter.cancelDiscovery();
	    Log.d(TAG, "...Connecting...");

	    try {
	    	btSocket.connect();
	    	baglan_toggle.setChecked(true);
	    	Log.d(TAG, "...Connection ok...");
	    }
	    catch (IOException e) {
	    	try {
	    		btSocket.close();
	    		baglan_toggle.setChecked(false);
	    	}
	    	catch (IOException e2) {
	    		errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
	    	}
	    }
	    
	    Log.d(TAG, "...Create Socket...");

	    try {
	    	outStream = btSocket.getOutputStream();
	    }
	    catch (IOException e) {
	    	baglan_toggle.setChecked(false);
	    	errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
	    }
	}
  
	private void disconnectBluetooth() {
		Log.d(TAG, "...In onPause()...");
		if (outStream != null) {
			try {
				outStream.flush();
			}
			catch (IOException e) {
				errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
			}
		}
		try {
			btSocket.close();
		}
		catch (IOException e2) {
			errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
		}
		baglan_toggle.setChecked(false);
	}
  
	@Override
	public void onResume() {
		super.onResume();
		connectBluetooth();
		sensorManager.registerListener(accelerationListener, acc, SensorManager.SENSOR_DELAY_NORMAL);
		sensorManager.registerListener(accelerationListener, mag, SensorManager.SENSOR_DELAY_NORMAL);
	}
  
	@Override
	public void onPause() {
		super.onPause();
		disconnectBluetooth();
	}

	@Override
	protected void onStop() {
		sensorManager.unregisterListener(accelerationListener);
		super.onStop();
	}
	
	private void checkBTState() {
		if(btAdapter==null) {
			errorExit("Fatal Error", "Bluetooth not support");
		} else {
			if (btAdapter.isEnabled()) {
				Log.d(TAG, "...Bluetooth ON...");
			} else {
				Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
				startActivityForResult(enableBtIntent, 1);
			}
		}
	}
  
	private void errorExit(String title, String message){
		Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
		finish();
	}
  
	private void sendData(String message) {
		byte[] msgBuffer = message.getBytes();
		Log.d(TAG, "...Send data: " + message + "...");
		try {
			outStream.write(msgBuffer);
	    }
	    catch (IOException e) {
	      String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
	      errorExit("Fatal Error", msg);
	    }
	}
}